#include "plane.h"
#include "pch/Eigen.h"

using namespace BaseGeo;


#define INITIALIZE_COLUMN(dim, triangle) \
    {triangle.vertices[0].dim, triangle.vertices[1].dim, triangle.vertices[2].dim}


static DetSet calDets(
    Eigen::Vector3d x_column,
    Eigen::Vector3d y_column,
    Eigen::Vector3d z_column
)
{
    Eigen::Matrix3d matrix_xyz, matrix_xz, matrix_xy, matrix_yz;

    matrix_xyz << x_column, y_column, z_column;
    matrix_xz << x_column, z_column, Eigen::Vector3d::Ones();
    matrix_xy << x_column, y_column, Eigen::Vector3d::Ones();
    matrix_yz << y_column, z_column, Eigen::Vector3d::Ones();

    return {
        .det_xyz = matrix_xyz.determinant(),
        .det_xz = matrix_xz.determinant(),
        .det_yz = matrix_yz.determinant(),
        .det_xy = matrix_xy.determinant()
    };
}


Plane3D::Plane3D() : det_set({0.0, 0.0, 0.0, 0.0}) {}

Plane3D::Plane3D(const Triangle& triangle)
    : det_set(
        calDets(
            INITIALIZE_COLUMN(x, triangle),
            INITIALIZE_COLUMN(y, triangle),
            INITIALIZE_COLUMN(z, triangle)
        )
    )
{}


double Plane3D::QueryZ(const double x, const double y) const
{
    double z = 0.0;

    z = y * det_set.det_xz - x * det_set.det_yz + det_set.det_xyz;
    z /= det_set.det_xy;

    return z;
}